home *** CD-ROM | disk | FTP | other *** search
- // WAISControl.m
- //
- // Free software created 1 Feb 1992
- // by Paul Burchard <burchard@math.utah.edu>.
-
- #import "WAISControl.h"
- #import "Wais.h"
- #import "QuestionDoc.h"
- #import "SourceDoc.h"
- #import "BrowserPane.h"
- #import "IconWellControl.h"
- #import "MailSpeaker.h"
- #import <appkit/appkit.h>
- #import <sys/file.h>
-
-
- @implementation WAISControl
-
-
- // ----------------------- PREFERENCES ------------------------ //
-
-
- static NXDefaultsVector WAIStationDefaults =
- {
- { "SystemFolder", "/LocalLibrary/WAIS" },
- { "UserFolder", "~/Library/WAIS" },
- { "OpenOnRetrieval", "YES" },
- { "MaxSearchResults", "30" },
- { "MailListAddress", "listserv@think.com" },
- { "MailListMessage", "ADD wais-talk\nADD wais-interest\nADD wais-discussion\n" },
- { "BugReportAddress", "burchard@math.utah.edu" },
- { "BugReportCC", "bug-wais@think.com" },
- { "BugReportSubject", "Comments on WAIStation.app " WAISTATION_VERSION " for NeXT" },
- { "BugReportMessage", "Please help us in making the WAIS software better.
- Please answer candidly.
-
- How was the installation on the NeXT?
- How is the documentation?
- Comments on the server code:
- Comments on the NeXT interface:
- Comments on the existing WAIS sources on the net:
- What WAIS sources would you like to see:
- Would you like to help? In what way?
- General comments:
- " },
- { NULL }
- };
-
- + initialize
- {
- NXRegisterDefaults("WAIStation", WAIStationDefaults);
- return self;
- }
-
- // Returns NXAtom-ized version of full folder name.
- // Adds this name to the search path for the WaisClass (if not already there).
- // Name will be inserted at beginning if where<0, at end if where>0.
- // Note: subname may be NULL.
- - (NXAtom)addToPath:WaisClass inPos:(int)where
- subdir:(const char *)subname ofFolder:(const char *)name
- {
- char *buf;
- const char *home;
- NXAtom rtn;
- int i, len, cnt;
- id flist;
-
- // Valid folder?
- if(!name) return 0;
- if(!(name[0]=='/' || (name[0]=='~' && name[1]=='/'))) return 0;
-
- // Create buffer...
- home = NXHomeDirectory();
- len = 1 + strlen(name) + strlen("/");
- if(home) len += strlen(home);
- if(subname) len += strlen(subname);
- buf = s_malloc(len);
- if(!buf) return 0;
-
- // Replace initial '~' with home directory.
- if(name[0] == '~')
- {
- if(home) strcpy(buf, home);
- strcat(buf, name+1);
- }
- else strcpy(buf, name);
- len = strlen(buf);
-
- // Append subfolder if any (fix trailing '/').
- if(subname)
- {
- if(buf[len-1] != '/') strcat(buf, "/");
- strcat(buf, subname);
- }
- else if(buf[len-1] == '/') buf[len-1] = 0;
-
- // Append atomized version to WaisClass's path and return it.
- rtn = NXUniqueString(buf); s_free(buf);
- flist = [WaisClass folderList]; cnt = [flist count];
- for(i=0; i<cnt; i++) if(rtn == *((NXAtom *)[flist elementAt:i])) break;
- if(i >= cnt)
- {
- if(where > 0) [flist addElement:(void *)&rtn];
- else [flist insert:(void *)&rtn at:0];
- }
- return rtn;
- }
-
- - createFolder:(const char *)name onError:(const char *)alertMsg
- {
- char cmd[2*MAXPATHLEN];
-
- [Wais lockFileIO];
- if(!name)
- {
- if(stringTable) NXRunAlertPanel(
- [stringTable valueForStringKey:"WAIStation"],
- [stringTable valueForStringKey:alertMsg],
- [stringTable valueForStringKey:"OK"], NULL, NULL);
- else { fprintf(stderr, "%s\n", alertMsg); fflush(stderr); }
- [Wais unlockFileIO];
- return nil;
- }
- if(0 == access(name, R_OK|W_OK|X_OK))
- { [Wais unlockFileIO]; return self; }
- sprintf(cmd, "mkdirs \'%s\'", name);
- system(cmd);
- if(0 == access(name, R_OK|W_OK|X_OK))
- { [Wais unlockFileIO]; return self; }
- if(stringTable) NXRunAlertPanel(
- [stringTable valueForStringKey:"WAIStation"],
- [stringTable valueForStringKey:alertMsg],
- [stringTable valueForStringKey:"OK"], NULL, NULL);
- else { fprintf(stderr, "%s\n", alertMsg); fflush(stderr); }
- [Wais unlockFileIO];
- return nil;
- }
-
- - usePrefs
- {
- const char *basefolder, *number;
- NXAtom folder;
- int limit;
-
- // Set flag to open or not open docs as they are retrieved.
- if(!NXGetDefaultValue("WAIStation", "OpenOnRetrieval")
- || 'Y'==*NXGetDefaultValue("WAIStation", "OpenOnRetrieval")
- || 'y'==*NXGetDefaultValue("WAIStation", "OpenOnRetrieval"))
- isOpenOnRetrieval = YES;
- else isOpenOnRetrieval = NO;
-
- // Set class-wide search limit for questions.
- if((number=NXGetDefaultValue("WAIStation", "MaxSearchResults"))
- && 1==sscanf(number, " %d ", &limit))
- [WaisQuestion setSearchLimit:limit];
-
- // Create user directories if necessary and prepend to appropriate paths.
- if(NXGetDefaultValue("WAIStation", "UserFolder"))
- basefolder = NXGetDefaultValue("WAIStation", "UserFolder");
- else basefolder = "~/Library/WAIS";
-
- folder = [self addToPath:[WaisSource class] inPos:(-1)
- subdir:"sources" ofFolder:basefolder];
- [self createFolder:folder
- onError:"Can't create folder for WAIS sources"];
-
- folder = [self addToPath:[WaisDocument class] inPos:(-1)
- subdir:"documents" ofFolder:basefolder];
- [self createFolder:folder
- onError:"Can't create folder for WAIS documents"];
-
- folder = [self addToPath:[WaisQuestion class] inPos:(-1)
- subdir:"questions" ofFolder:basefolder];
- [self createFolder:folder
- onError:"Can't create folder for WAIS questions"];
-
- // Append system directories (if any) to appropriate paths.
- if(NXGetDefaultValue("WAIStation", "SystemFolder"))
- {
- basefolder = NXGetDefaultValue("WAIStation", "SystemFolder");
-
- [self addToPath:[WaisSource class] inPos:1
- subdir:"sources" ofFolder:basefolder];
- [self addToPath:[WaisSource class] inPos:1
- subdir:"wais-sources" ofFolder:basefolder];
- [self addToPath:[WaisDocument class] inPos:1
- subdir:"documents" ofFolder:basefolder];
- [self addToPath:[WaisQuestion class] inPos:1
- subdir:"questions" ofFolder:basefolder];
- }
- return self;
- }
-
- - updatePrefs:sender
- {
- char number[128];
-
- // Get new prefs from panel and save in database.
- if([prefsIsOpenOnRetrieval state] != 0)
- NXWriteDefault("WAIStation", "OpenOnRetrieval", "YES");
- else NXWriteDefault("WAIStation", "OpenOnRetrieval", "NO");
- sprintf(number, "%d", [prefsSearchLimit intValue]);
- NXWriteDefault("WAIStation", "MaxSearchResults", number);
- if([prefsSystemFolder stringValue])
- NXWriteDefault("WAIStation",
- "SystemFolder", [prefsSystemFolder stringValue]);
- if([prefsUserFolder stringValue])
- NXWriteDefault("WAIStation",
- "UserFolder", [prefsUserFolder stringValue]);
- [self usePrefs];
- return self;
- }
-
- - prefs:sender
- {
- const char *number;
- int limit;
-
- if(!prefsPanel) [NXApp loadNibSection:"Preferences.nib" owner:self];
- if(!NXGetDefaultValue("WAIStation", "OpenOnRetrieval")
- || 'Y'==*NXGetDefaultValue("WAIStation", "OpenOnRetrieval")
- || 'y'==*NXGetDefaultValue("WAIStation", "OpenOnRetrieval"))
- [prefsIsOpenOnRetrieval setState:1];
- else [prefsIsOpenOnRetrieval setState:0];
-
- if((number=NXGetDefaultValue("WAIStation", "MaxSearchResults"))
- && 1==sscanf(number, " %d ", &limit))
- [prefsSearchLimit setIntValue:limit];
- [prefsSearchLimit sendAction:[prefsSearchLimit action]
- to:[prefsSearchLimit target]];
-
- [prefsSystemFolder
- setStringValue:NXGetDefaultValue("WAIStation", "SystemFolder")];
- [prefsUserFolder
- setStringValue:NXGetDefaultValue("WAIStation", "UserFolder")];
-
- [prefsPanel update];
- [prefsPanel makeKeyAndOrderFront:self];
-
- // Set up controller for icon wells; transfer info from TextFields.
- if(!prefsIWC) prefsIWC =
- [[IconWellControl alloc] initWindow:prefsPanel];
- [prefsSystemFolder sendAction:[prefsSystemFolder action]
- to:[prefsSystemFolder target]];
- [prefsUserFolder sendAction:[prefsUserFolder action]
- to:[prefsUserFolder target]];
- return self;
- }
-
- + (const char *)defaultFolder
- {
- if(NXGetDefaultValue("WAIStation", "UserFolder"))
- return NXGetDefaultValue("WAIStation", "UserFolder");
- else return [[Wais folderList] elementAt:0];
- }
-
- // ----------------------- RETRIEVAL ------------------------ //
-
-
- // Callback from retrieval thread to main thread.
- - retrievalDone:data
- {
- int docAt, ok;
- id doc, check_rtn;
-
- if(!data || ![data isKindOf:[List class]]
- || ![[data objectAt:0] isKindOf:[Wais class]])
- return nil;
- doc = [data objectAt:0];
- check_rtn = [data objectAt:1];
- [data free];
-
- // If successfully retrieved and user desires docs to be opened on
- // retrieval, pop open doc.
- if(check_rtn && isOpenOnRetrieval) [self openFile:[doc key] ok:&ok];
-
- // Enable browser entry for doc if check_rtn non-nil, else remove it.
- if(documentPaletteBrowser
- && (docAt=[documentPaletteBrowser indexOfEntry:[doc key]])>=0)
- {
- if(check_rtn) [documentPaletteBrowser setEntryEnabled:YES at:docAt];
- else [documentPaletteBrowser removeEntryAt:docAt];
- }
- else if(sourcePaletteBrowser
- && (docAt=[sourcePaletteBrowser indexOfEntry:[doc key]])>=0)
- {
- if(check_rtn) [sourcePaletteBrowser setEntryEnabled:YES at:docAt];
- else [sourcePaletteBrowser removeEntryAt:docAt];
- }
- return self;
- }
-
- any_t retrieval_thread(any_t rawArgs)
- {
- retrieval_args args = (retrieval_args)rawArgs;
- id doc, src, check_rtn, data;
-
- while(YES)
- {
- // Wait for retrieval requests to show up in list.
- mutex_lock(args->requestMutex);
- while([args->docList count] <= 0)
- condition_wait(args->requestCondition, args->requestMutex);
- doc = [args->docList objectAt:0];
- mutex_unlock(args->requestMutex);
- if(!doc) continue;
-
- // Only one retrieval at a time, since same port may be used.
- // If doc file describes a source, load it into Wais system.
- // Else write auxiliary WAIS file to preserve access info.
- check_rtn = [doc retrieve];
- if(check_rtn)
- {
- if([doc valueForStringKey:":type"]
- && 0==strcmp([doc valueForStringKey:":type"], "WSRC"))
- {
- src = [[WaisSource alloc] initKey:[doc key]];
- [src readWaisFile];
- }
- else [doc writeWaisFile];
- }
-
- // Report back:
- // 1. Pop open retrieved doc if necessary.
- // 2. Enable browser entry if successful, else remove it.
- // (Use callback to main thread since AppKit is not thread-proof.
- // Callback will free data list.)
- // (Note: [NXApp delegate] = us.)
- data = [[List alloc] init];
- [data addObject:doc]; [data addObject:check_rtn];
- [Wais callback:[NXApp delegate]
- perform:@selector(retrievalDone:) with:data];
-
- // Remove entry from request list.
- mutex_lock(args->requestMutex);
- [args->docList removeObjectAt:0];
- mutex_unlock(args->requestMutex);
- }
- // Never reaches this.
- return 0;
- }
-
- - restartThread
- {
- // Already running?
- if(retrievalThread) return nil;
-
- // Create and detach thread.
- retrievalArgs.docList = retrievalList;
- retrievalArgs.requestMutex = requestMutex = mutex_alloc();
- retrievalArgs.requestCondition = requestCondition = condition_alloc();
- retrievalThread = cthread_fork(retrieval_thread, (any_t)&retrievalArgs);
- if(!retrievalThread) return nil;
- cthread_detach(retrievalThread);
- return self;
- }
-
- - terminateThread
- {
- int i;
-
- // Try to abort the retrieval thread.
- //!!! Zapping threads may screw up the mutex locking, so we don't
- //!!! try to recycle old mutexes and conditions. Even if old thread stays
- //!!! around, it's probably not doing much, so its freedom from the
- //!!! new mutexes shouldn't be a problem.
- if(!retrievalThread) return self;
- thread_suspend(cthread_thread(retrievalThread));
- cthread_abort(retrievalThread);
- retrievalThread = 0;
- requestMutex = 0;
- requestCondition = 0;
- [Wais waisNewLocks];
-
- // Clear retrieval request list.
- // Update palettes (removing disabled entries).
- [retrievalList empty];
- for(i=[documentPaletteBrowser count]-1; i>=0; i--)
- if(![documentPaletteBrowser isEntryEnabledAt:i])
- [documentPaletteBrowser removeEntryAt:i];
- [documentPaletteBrowser update];
- for(i=[sourcePaletteBrowser count]-1; i>=0; i--)
- if(![sourcePaletteBrowser isEntryEnabledAt:i])
- [sourcePaletteBrowser removeEntryAt:i];
- [sourcePaletteBrowser update];
- return self;
- }
-
- - cancelRetrievals:sender
- {
- [self terminateThread];
- [self restartThread];
- return self;
- }
-
- //!!! This method should be called before doing any operation that might
- //!!! access a WaisDocument. If it is being retrieved, you should
- //!!! not access it as that might collide with operations in the
- //!!! retrieval thread.
- - (BOOL)isDocumentBeingRetrieved:waisDoc
- {
- int docAt;
-
- if(requestMutex) mutex_lock(requestMutex);
- docAt = [retrievalList indexOf:waisDoc];
- if(requestMutex) mutex_unlock(requestMutex);
- if(docAt!=NX_NOT_IN_LIST && docAt>=0) return YES;
- return NO;
- }
-
- - retrieveDocuments:(const char *)keyList
- {
- int docAt;
- char *docKeys, *thisKey, *nextKey;
- id doc, inBrowser;
- BOOL isSource;
-
- // Assumes keyList is TAB-separated list of keys.
- if(!keyList || !retrievalThread) return nil;
- if(!(docKeys = s_malloc(strlen(keyList) + 1))) return nil;
- strcpy(docKeys, keyList);
- for(thisKey=docKeys, nextKey=strchr(thisKey, '\t');
- thisKey; thisKey=nextKey, nextKey=strchr(thisKey?thisKey:"", '\t'))
- {
- if(nextKey) *nextKey++ = 0;
-
- // Check if doc is aleady retrieved or being retrieved (then ignore).
- if(!(doc = [WaisDocument objectForKey:thisKey])) continue;
- if([self isDocumentBeingRetrieved:doc] || [doc isRetrieved])
- continue;
-
- // Check if it is really a source.
- isSource = NO;
- inBrowser = documentPaletteBrowser;
- if([doc valueForStringKey:":type"]
- && 0==strcmp([doc valueForStringKey:":type"], "WSRC"))
- isSource = YES;
- if(isSource) inBrowser = sourcePaletteBrowser;
-
- // Enter into correct palette browser, but disabled.
- if(inBrowser)
- {
- docAt = [inBrowser indexAddEntry:[doc key]];
- [inBrowser setEntryEnabled:NO at:docAt];
- [inBrowser update];
- }
-
- // Enter doc into queue and notify thead of retrieval request.
- if(requestMutex) mutex_lock(requestMutex);
- [retrievalList addObjectIfAbsent:doc];
- if(requestMutex) mutex_unlock(requestMutex);
- if(requestCondition) condition_signal(requestCondition);
- }
- s_free(docKeys);
- return self;
- }
-
- - retrieveDocumentsFrom:sender
- {
- return [self retrieveDocuments:[sender stringValue]];
- }
-
-
- // ----------------------- PANEL SETUP ----------------------- //
-
-
- - init
- {
- id Handlers;
-
- [super init];
-
- // Classify file types.
- Handlers = [[List alloc] initCount:0];
- [Handlers addObject:[QuestionDoc class]];
- [Handlers addObject:[SourceDoc class]];
- [super setDocHandlers:Handlers];
- launchWithCreateDoc = YES;
-
- // Keep track of retrieval threads.
- retrievalList = [[List alloc] initCount:0];
- retrievalThread = 0;
- return self;
- }
-
- - free
- {
- if(retrievalThread) [self terminateThread];
- [retrievalList free];
- if(requestMutex) mutex_free(requestMutex);
- if(requestCondition) condition_free(requestCondition);
- return [super free];
- }
-
- - appDidInit:sender
- {
- char userInfo[1024];
- char hostname[512];
-
- [super appDidInit:sender];
-
- // Enable Alert Panels for Wais classes.
- [Wais setStringTable:stringTable];
-
- // Set up according to preferences.
- [self usePrefs];
-
- // Set user registration string.
- gethostname(hostname, 512); hostname[512-1] = 0;
- sprintf(userInfo, "WAIStation.app %s, from host: %s, user: %s",
- WAISTATION_VERSION, hostname, WAIS_USER);
- [WaisSource registerUser:userInfo];
-
- // Pop up source and doc palettes.
- [self sourcePalette:self];
- [self documentPalette:self];
- [sourcePalettePanel makeKeyAndOrderFront:self];
-
- // Start retrieval thread.
- // Must be done after doc and source palette created if we want updates!
- [self restartThread];
- return self;
- }
-
- - help:sender
- {
- if(!helpPanel) [NXApp loadNibSection:"Help.nib" owner:self];
- [helpPanel makeKeyAndOrderFront:self];
- return self;
- }
-
- - info:sender
- {
- if(!infoPanel) [NXApp loadNibSection:"Info.nib" owner:self];
- [infoPanel makeKeyAndOrderFront:self];
- return self;
- }
-
- - bugReport:sender
- {
- //!!! Note the "MailSendDemo" port is undocumented.
- id mailSpeaker = [[MailSpeaker alloc] init];
- port_t mailPort = NXPortFromName("MailSendDemo", NULL);
-
- if(!mailSpeaker || mailPort==PORT_NULL)
- { [mailSpeaker free]; return nil; }
- [mailSpeaker setSendPort:mailPort];
- [mailSpeaker openSend];
- if(NXGetDefaultValue("WAIStation", "BugReportAddress"))
- [mailSpeaker setTo:NXGetDefaultValue("WAIStation",
- "BugReportAddress")];
- if(NXGetDefaultValue("WAIStation", "BugReportCC"))
- [mailSpeaker setCc:NXGetDefaultValue("WAIStation", "BugReportCC")];
- if(NXGetDefaultValue("WAIStation", "BugReportSubject"))
- [mailSpeaker setSubject:NXGetDefaultValue("WAIStation",
- "BugReportSubject")];
- if(NXGetDefaultValue("WAIStation", "BugReportMessage"))
- [mailSpeaker setBody:NXGetDefaultValue("WAIStation",
- "BugReportMessage")];
- [mailSpeaker free];
- port_deallocate(task_self(), mailPort);
- return self;
- }
-
- - signMeUp:sender
- {
- //!!! Note the "MailSendDemo" port is undocumented.
- id mailSpeaker = [[MailSpeaker alloc] init];
- port_t mailPort = NXPortFromName("MailSendDemo", NULL);
-
- if(!mailSpeaker || mailPort==PORT_NULL)
- { [mailSpeaker free]; return nil; }
- [mailSpeaker setSendPort:mailPort];
- [mailSpeaker openSend];
- if(NXGetDefaultValue("WAIStation", "MailListAddress"))
- [mailSpeaker setTo:NXGetDefaultValue("WAIStation", "MailListAddress")];
- [mailSpeaker setSubject:"SUBSCRIBE"];
- if(NXGetDefaultValue("WAIStation", "MailListMessage"))
- [mailSpeaker setBody:NXGetDefaultValue("WAIStation",
- "MailListMessage")];
- [mailSpeaker free];
- port_deallocate(task_self(), mailPort);
- return self;
- }
-
- - sourcePalette:sender
- {
- int i, j, n, m;
- BOOL quiet;
- id srcList, srcPath;
- const char **srcFolder;
-
- if(!(srcPath = [WaisSource folderList])) return nil;
- if(!sourcePalettePanel)
- {
- [NXApp loadNibSection:"SourcePalette.nib" owner:self];
- [[sourcePaletteBrowser setAlphabetized:YES] setAbbreviated:YES];
- [sourcePaletteBrowser setEditable:YES];
- }
-
- // Load all directories in source path (ignore missing ones).
- [sourcePaletteBrowser clear];
- quiet = [Wais isQuiet];
- [Wais setQuiet:YES];
- m = [srcPath count];
- for(j=0; j<m; j++) if((srcFolder=(const char **)[srcPath elementAt:j])
- && (*srcFolder) && (srcList=[WaisSource loadFolder:*srcFolder]))
- {
- n = [srcList count];
- for(i=0; i<n; i++)
- [sourcePaletteBrowser addEntry:[[srcList objectAt:i] key]];
- [srcList free];
- }
- [Wais setQuiet:quiet];
- [sourcePaletteBrowser update];
- [sourcePalettePanel orderFront:self];
-
- if(!sourcePaletteIWC) sourcePaletteIWC =
- [[IconWellControl alloc] initWindow:sourcePalettePanel];
- return self;
- }
-
- - documentPalette:sender
- {
- int i, j, n, m;
- BOOL quiet;
- id docList, docPath;
- const char **docFolder;
-
- if(!(docPath = [WaisDocument folderList])) return nil;
- if(!documentPalettePanel)
- {
- [NXApp loadNibSection:"DocumentPalette.nib" owner:self];
- [[documentPaletteBrowser setAlphabetized:YES] setAbbreviated:YES];
- [documentPaletteBrowser setEditable:YES];
- }
-
- // Load all directories in document path (ignore missing ones).
- [documentPaletteBrowser clear];
- quiet = [Wais isQuiet];
- [Wais setQuiet:YES];
- m = [docPath count];
- for(j=0; j<m; j++) if((docFolder=(const char **)[docPath elementAt:j])
- && (*docFolder) && (docList=[WaisDocument loadFolder:*docFolder]))
- {
- n = [docList count];
- for(i=0; i<n; i++)
- {
- if([self isDocumentBeingRetrieved:[docList objectAt:i]])
- continue;
- else if([[docList objectAt:i] isRetrieved])
- [documentPaletteBrowser addEntry:[[docList objectAt:i] key]];
- }
- [docList free];
- }
- [Wais setQuiet:quiet];
- [documentPaletteBrowser update];
- [documentPalettePanel orderFront:self];
-
- if(!documentPaletteIWC) documentPaletteIWC =
- [[IconWellControl alloc] initWindow:documentPalettePanel];
- return self;
- }
-
-
- // ----------------------- DELEGATED FILE OPS ------------------------ //
-
-
- - (int)openFile:(const char *)fileName ok:(int *)flag
- {
- int rtn;
-
- // Try to open in this application first, then in Workspace.
- if([super handlerForFile:fileName])
- {
- if([super openForHandlerAt:(-1) name:fileName]) *flag = YES;
- else *flag = NO;
- rtn = 0;
- }
- else
- {
- [Wais lockTransaction];
- [[NXApp appSpeaker] setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
- rtn = [[NXApp appSpeaker] openFile:fileName ok:flag];
- [Wais unlockTransaction];
- }
- return rtn;
- }
-
- - (int)removeFile:(const char *)fileName ok:(int *)flag
- {
- int rtn = 0;
- char *auxFile = 0;
- id doc = nil;
-
- // If a WaisDocument, set it as unretrieved
- // and delete the associated ".wais" file too.
-
- if(!fileName) return (-1);
- *flag = NO;
- if(doc = [WaisDocument objectForKey:fileName])
- {
- auxFile = s_malloc(1+strlen(fileName)+strlen(".wais"));
- if(!auxFile) return (-1);
- strcpy(auxFile, fileName); strcat(auxFile, ".wais");
- //!!! Potential thread conflict if doc is being retrieved.
- // (But shouldn't be a problem since such entries are disabled.)
- [doc setUnretrieved];
- }
- [Wais lockFileIO];
- if(doc) rtn = unlink(auxFile);
- if(rtn == 0) rtn = unlink(fileName);
- else unlink(fileName);
- [Wais unlockFileIO];
- if(auxFile) s_free(auxFile);
- if(rtn != 0) return rtn;
- *flag = YES;
- return 0;
- }
-
- @end
-